package GoDBusDemoSrv

import (
	"io/ioutil"
	"log"
	"os"
	"time"

	sdbus "github.com/godbus/dbus"
	"github.com/godbus/dbus/introspect"
)

const (
	iface_path = "/com/ccc/test/test"
	iface_name = "com.ccc.test.test"
)

type DemoDbusIfc struct {
}

func (ifc *DemoDbusIfc) GetName(isReal bool) (string, *sdbus.Error) {
	name := "dbus srv demo"
	if isReal {
		return name, nil
	} else {
		var dbusErr sdbus.Error
		dbusErr.Name = "test"
		var bodyStrList []string
		bodyStrList = append(bodyStrList, "1", "2", "3")
		dbusErr.Body = []interface{}{bodyStrList}

		return name, &dbusErr
	}
}

func (ifc *DemoDbusIfc) GetClass() (string, *sdbus.Error) {
	return "test class", nil
}

func getIntrospectableStr() string {
	data, err := ioutil.ReadFile("conf/dbusxml/com.ccc.test.test.xml")
	if err != nil {
		log.Print("conf/dbusxmlcom.ccc.test.test.xml read failed1", err)
	}

	return string(data)
}

func SrvTest() {

	testIface := &DemoDbusIfc{}

	//// 测试接口
	name, sdbusErr := testIface.GetName(false)
	log.Printf("name: %s", name)
	if sdbusErr != nil {
		log.Printf("sdbusErr.Name: %s, sdbusErr.Body: %v", sdbusErr.Name, sdbusErr.Body)
		// 解析body
		var bodyStrList []string
		err := sdbus.Store(sdbusErr.Body, &bodyStrList)
		if err != nil {
			log.Printf("sdbus Store failed: %v", sdbusErr.Body)
		}
		log.Printf("sdbus Store succeed: %v", bodyStrList)
	}

	//// 绑定接口
	sessionDBus, err := sdbus.SessionBus()
	if err != nil {
		log.Printf("sessionDBus get failed")
		return
	}

	reply, err := sessionDBus.RequestName(iface_name, sdbus.NameFlagDoNotQueue)
	if err != nil {
		panic(err)
	}

	if reply != sdbus.RequestNameReplyPrimaryOwner {
		log.Printf("%s already registered!", iface_name)
		os.Exit(1)
	}

	err = sessionDBus.Export(testIface, iface_path, iface_name)
	if err != nil {
		log.Printf("sessionDBus Export %v failed!", testIface)
	}
	log.Print("name:", sessionDBus.Names())

	//// 绑定自查接口（也非常重要，缺了无法调用)
	// 方法1：通过代码创建描述（此方法不能生成信号描述）
	introspectIface := &introspect.Interface{}
	introspectIface.Name = iface_name
	introspectIface.Methods = introspect.Methods(testIface)

	node := &introspect.Node{}
	node.Name = iface_name
	node.Interfaces = append(node.Interfaces, *introspectIface)

	dbusXMLStr := introspect.NewIntrospectable(node)
	log.Printf("dbusXMLStr: \n%s\n", dbusXMLStr)

	// 方法2：通过读取xml文件创建描述
	dbusXMLStr = introspect.Introspectable(getIntrospectableStr())
	log.Printf("dbusXMLStr: \n%s\n", dbusXMLStr)

	sessionDBus.Export(dbusXMLStr, iface_path, "org.freedesktop.DBus.Introspectable")

	// 定时发送信号
	go func() {
		for {
			time.Sleep(2 * time.Second)
			sessionDBus.Emit(iface_path, iface_name+".SendName", "dbus srv demo")
		}
	}()
}
